<template>
  <div class="container">
    <el-upload
      ref="uploadRef"
      class="upload-file"
      :name="name"
      :headers="headers"
      :action="uploadApi"
      :limit="limit"
      multiple
      :accept="convertFileType(fileType)"
      :show-file-list="false"
      :on-exceed="handleExceed"
      :on-change="handleChange"
      :on-error="handleUploadError"
      :on-progress="handleProgress"
      :on-success="handleUploadSuccess"
      :before-upload="handleBeforeUpload"
    >
      <slot>
        <el-button
          v-if="fileList.length<limit&&showUpload"
          size="small"
          :type="uploadPercentage?'warning':'primary'"
          class="btn-upload"
        >
          {{ uploadPercentage?'正在导入数据，请耐心等待...':'点击导入文件' }}
        </el-button>
        <!-- <div v-if="fileList.length">
      <strong>以下文件已导入成功</strong>
    </div> -->
        <ul
          class="file-item el-upload-list el-upload-list--text draglistmove"
          @click="maskClick"
        >
          <li
            v-for="(file,index) in fileList"
            v-show="file.dr===0"
            :key="file.id"
            class="el-upload-list__item is-success li-flex-box"
          >
            <a v-show="file.id !== showEditItem">
              <i class="el-icon-document " /> {{ file.attachmentName }}
            </a>

            <a v-show="file.id ===showEditItem">
              <el-input v-model="file.attachmentName" style="width:500px" autofocus size="mini" @change="saveEdit(file)" />
            </a>

            <span class="option-box">
              <span
                v-show="showRemove"
                class="option-icon"
                @click="handleBeforeRemove(file,index)"
              >
                <i class="el-icon-delete" />
              </span>
              <span
                v-show="showEdit"
                class="option-icon"
                @click="handleEdit(file)"
              >
                <i class="el-icon-edit" />
              </span>
              <!-- 所有文件可直接下载 -->
              <slot name="downloadBtn" :file="file">
                <a
                  class="option-icon link-item"
                  :href="url+'/'+file.attachmentUrl"
                  :download="file.attachmentName"
                >
                  <i class="el-icon-download" />
                </a>
              </slot>
              <span
                class="option-icon"
                @click="handlePreview(file)"
              >
                <i class="el-icon-zoom-in" />
              </span>
            </span>
          </li>
        </ul>
        <div v-show="showUpload" slot="tip" style="color:#999" color="#999" class="el-upload__tip">
          文件大小不超过{{ fileSize / 1024 /1024 }} M,支持{{ fileType }}类型
          <el-button v-show="showDownloadTemp" :loading="loading" size="mini" type="text" @click="downloadTemp">模板下载<i class="el-icon-download" /></el-button>
        </div>
        <div v-if="uploadPercentage" class="mask-upload" @click="maskClick">
          <el-progress
            :percentage="uploadPercentage"
            :status="uploadStatus"
          />
          <div class="btn-cancel">
            <span v-if="cancelStatus" @click.stop="cancelUploadFile"><i class="el-icon-close" /></span>
            <span v-if="clearStatus" @click.stop="clearUploadStatus"><i class="el-icon-close" /></span>
          </div>
        </div>
      </slot>
    </el-upload>
    <!-- 图片预览 -->
    <el-image-viewer
      v-if="imgDialogVisible"
      style="z-index:3000"
      :on-close="handleCloseImg"
      :url-list="[previewImg]"
    />
  </div>
</template>

<script>
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'
import { filterURL } from '@/utils'
import Sortable from 'sortablejs'
import { getShopAttachment, downloadFile } from '@/api/common.js'
import { getToken } from '@/utils/auth'
export default {
  name: 'FileUploader',
  components: { ElImageViewer },
  props: {
    data: {
      type: Array,
      default: () => {
        return []// 父组件传入的文件
      }
    },
    fileType: {// 支持文件上传类型
      type: String,
      default: '.xls,.xlsx,.jpg,.jpeg,.png,.pdf,.doc,.docx,.zip,.rar'
    },
    showDownloadTemp: {// 是否模板下载
      type: Boolean,
      default: true
    },
    showUpload: {// 是否显示上传按钮
      type: Boolean,
      default: true
    },
    showEdit: {// 是否显示编辑按钮
      type: Boolean,
      default: true
    },
    showRemove: {// 是否显示删除按钮
      type: Boolean,
      default: true
    },
    showDownload: {// 是否显示下载按钮
      type: Boolean,
      default: true
    },
    action: {
      type: String,
      // default: () => '/ads-admin/api/v1/adsEnclosureInfo/uploadFile' // 附件默认上传路径
      default: () => `/slm-admin/api/v1/file/uploadFile` // 附件默认上传路径
    },
    name: {
      type: String,
      default: 'file'
    },
    limit: {// 文件上传限制个数
      type: Number,
      default: 20
    },
    fileSize: {// 文件大小限制，单位mb
      type: Number,
      default: 1024 * 1024 * 100
    },
    beforeUpload: {
      type: Function,
      default: function() {
        return true
      }
    },
    configAttachmentId: {// 模板配置类型
      type: String,
      default: ''
    },
    beforeRemove: {
      type: Function,
      default: function() {
        return true
      }
    }
  },
  inject: {
    // 获取父组件的provide
    elForm: {
      default: ''
    },
    elFormItem: {
      default: ''
    }
  },
  data() {
    return {
      previewImg: '', // 图片预览
      loading: false,
      templateData: [], // 模板附件
      imgDialogVisible: false,
      showEditItem: '',
      url: `/pdf-file/`,
      loadFlag: false,
      headers: {
        // 文件上传请求头
        'X-Token': this.$store.getters.token ? getToken() : '',
        'Authorization': this.$store.getters.token ? 'Bearer ' + getToken() : ''
      },
      fileList: [],
      cancelStatus: false, // 是否需要取消上传
      clearStatus: false, // 是否可以清除组件上传状态
      uploadPercentage: 0, // 上传百分比
      uploadStatus: 'exception' // 上传是否失败，失败时会设置为 exception
    }
  },
  computed: {
    uploadApi() {
      return this.action
    }
  },
  watch: {
    data: {
      handler(v) {
        this.fileList = v
      },
      immediate: true
    }
  },
  mounted() {
    this.listmove()
  },
  methods: {
    downloadTemp() {
      this.loading = true
      getShopAttachment(this.configAttachmentId).then(res => {
        if (res.success === 1 && res.data.length > 0) {
          this.templateData = res.data
          this.templateData.forEach(item => {
            let fileName = item.attachmentName
            if (fileName.replace(/(.*)\.(\w+)$/g, '$2') !== item.typeName.replace(/\.(\w+)$/, '$1')) {
              fileName = `${fileName}.${item.typeName.replace('.', '')}`
            }
            return downloadFile(item.attachmentUrl).then(res => {
              const t = URL.createObjectURL(res)
              const a = document.createElement('a')
              a.href = t
              a.download = fileName
              a.click()
              setTimeout(() => {
                URL.revokeObjectURL(t)
              }, 0)
            })
          })
          setTimeout(() => {
            this.loading = false
          }, 1000)
        } else {
          this.loading = false
          this.$message.warning('暂无模板可下载')
        }
      })
    },
    convertFileType(data) {
      const fileTypeList = []
      data.split(',').forEach(el => {
        if (el[0] !== '.') {
          fileTypeList.push('.' + el)
        } else fileTypeList.push(el)
      })
      const list = fileTypeList.map(e => e).join(',').toLowerCase().replace('.word', '.doc,.docx').replace(/\.xlsx|\.excel/g, '.xlsx,.xls').replace(/\.pptx?/g, '.ppt,.pptx').split(',')
      return list.map(e => `${e}`).join(',')
    },
    // 关闭图片预览
    handleCloseImg() {
      this.imgDialogVisible = false
    },
    // 拖拽排序功能
    listmove() {
      const el = document.querySelector('.draglistmove')
      Sortable.create(el, {
        onEnd: e => {
          const s = e.newIndex
          const o = e.oldIndex
          setTimeout(() => {
            const data = this.fileList[s]
            this.fileList[s] = this.fileList[o]
            this.fileList[o] = data
            this.$emit('upload-success', { file: {}, list: this.fileList })
          }, 100)
        }
      })
    },
    handleEdit(file) {
      if (this.showEditItem === file.id) {
        this.showEditItem = ''
      } else {
        this.showEditItem = file.id
      }
    },
    saveEdit(file) {
      this.showEditItem = ''
      this.$emit('upload-success', { file: file, list: this.fileList })
    },

    handlePreview(file) {
      const fileExtension = file.attachmentUrl.substring(file.attachmentUrl.lastIndexOf('.') + 1).toLowerCase()
      if (fileExtension === 'pdf') { // pdf预览
        const url = this.url + file.attachmentUrl
        const routeData = this.$router.resolve({
          path: '/viewFile',
          query: {
            src: btoa(url)
          }
        })
        window.open(routeData.href, '_blank')
      } else if (fileExtension === 'jpg' || fileExtension === 'jpeg' || fileExtension === 'png') {
      // 图片预览
        this.imgDialogVisible = true
        if (file.attachmentUrl.indexOf('http') !== -1) {
          const url = file.attachmentUrl.split('cn')
          this.previewImg = process.env.VUE_APP_BPMPIC_PREFIX + url[url.length - 1]
        } else {
          this.previewImg = filterURL(file.attachmentUrl)
        }
      } else if (fileExtension === 'doc' || fileExtension === 'docx' || fileExtension === 'xlsx') {
        // word,excel预览
        window.open(`${process.env.VUE_APP_OFFICE_PREFIX}?src=` + filterURL(file.attachmentUrl))
      } else {
        this.$message.warning('该文件类型不支持预览')
      }
    },
    handleBeforeUpload: function(file) {
      this.loadFlag = true
      // 上传前校验
      // const accept = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']
      // var isExcel = accept.includes(file.type)
      var isLt2M = file.size < this.fileSize
      // if (!isExcel) {
      //   this.$message.error('只能上传EXCEL文件!')
      // }
      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过 ' + (this.fileSize / 1024 / 1024) + 'M!')
      }
      if (isLt2M) {
        return this.beforeUpload(file)
      } else {
        return false
      }
    },
    handleProgress(event, file) {
      this.cancelStatus = true // 展示中断按钮
      // 上传中 event.percent 百分比
      this.uploadStatus = 'exception' // 上传状态置空,
      this.uploadPercentage = parseFloat(event.percent.toFixed(1))
      if (this.uploadPercentage > 99) {
        this.uploadPercentage = 99.0
      }
    },
    handleUploadSuccess(response, file) {
      this.cancelStatus = false // 隐藏取消按钮
      this.loadFlag = false
      // 上传成功回调
      if (response.success === 1) {
        this.uploadPercentage = 0// 上传进度归零, 隐藏进度框
        const fileData = {
          attachmentUrl: (response.data && response.data.attachmentUrl) || '', // 文件路径
          remark: (response && response.msg) || '', // 备注
          attachmentName: (response.data && response.data.attachmentName) || '', // 文件名
          id: (response.data && response.data.id) || '', // id
          typeName: (response.data && response.data.typeName) || '', // 附件类型
          createTime: (response.data && response.data.createTime) || '', // 创建时间
          createBy: (response.data && response.data.createBy) || '', // 创建人
          dr: (response.data && response.data.dr) || 0,
          // configAttachmentId: (response.data && response.data.id) || '', // 附件模板配置id todo
          // modelId: (response.data && response.data.id) || '', // 附件模板配置id todo
          configAttachmentId: this.configAttachmentId || ''// 附件类型
        }
        this.fileList.push(fileData)
        const tempArr = this.fileList.filter(el => el.dr === 0)
        this.$emit('upload-success', { file: fileData, list: this.fileList, fileLength: tempArr.length })
      } else {
        if (response.code === 401 || response.code === '401' || response.status === 401) {
          this.refreshToken({}, () => {
            this.refreshHeaders()
          })
        } else {
          this.uploadStatus = 'exception'
          this.$message.error('上传失败: ' + response.msg)
          this.clearStatus = true
        }
        this.$refs.uploadRef.clearFiles()
      }
      this.$emit('upload-finish', response)
    },
    handleUploadError(err, file) {
      this.loadFlag = false
      // 上传失败
      const res = JSON.parse(JSON.stringify(err))
      if (res.code === 401 || res.code === '401' || res.status === 401) {
        this.refreshToken({}, () => {
          this.refreshHeaders()
        })
      } else {
        this.$message.error('上传失败: ' + err)
        this.uploadStatus = 'exception'
        this.clearStatus = true
      }
      this.$refs.uploadRef.clearFiles()
    },
    handleChange(file) {
      this.$emit('on-change', '')
    },
    handleExceed(files, fileList) {
      this.$message.warning(`最多只能上传 ${this.limit} 个文件`)
    },
    clearUploadFile() {
      this.uploadStatus = 'exception'
      this.uploadPercentage = 0
      this.cancelStatus = false
      this.clearStatus = false
      this.$refs.uploadRef.clearFiles()
    },
    /**
       *@methods:clearUploadStatus
       *@description: 当上传失败时清空上传组件里面的状态值
       **/
    clearUploadStatus() {
      this.uploadPercentage = 0
      this.clearStatus = false
      this.clearUploadFile()
    },
    /**
       *@methods:cancelUploadFile
       *@description:点击取消按钮 触发中断事件
       **/
    cancelUploadFile() {
      this.$refs.uploadRef.abort()
      this.uploadPercentage = 0
      this.$message({
        type: 'success',
        message: '上传已中断,请重新上传文件'
      })
      this.clearUploadFile()
    },
    maskClick(event) {
      // 阻止默认的文件弹出框
      event.stopImmediatePropagation()
    },
    handleBeforeRemove(file) {
      const before = this.beforeRemove()
      if (before && before.then) {
        before.then(() => {
          this.onRemove(file)
        })
      } else if (before !== false) {
        this.onRemove(file)
      }
    },
    onRemove(file) {
      const index = this.fileList.findIndex(v => v.id === file.id)
      if (index > -1) {
        this.fileList[index].dr = 1
      }
      const tempArr = this.fileList.filter(el => el.dr === 0)
      this.$emit('remove', { file: file, list: this.fileList, fileLength: tempArr.length })
    },
    refreshHeaders() {
      this.headers = {
        'X-Token': this.$store.getters.token ? getToken() : '',
        'Authorization': this.$store.getters.token ? 'Bearer ' + getToken() : ''
      }
    }
  }
}
</script>

<style lang='scss' scoped>
.container{
  min-height: 100px;
}
.li-flex-box{
  min-width: 400px;
  max-width: 700px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
  .upload-file{
    position: relative;
    line-height: 30px;
    /deep/.el-upload{
      width: 100%;
      text-align: left;
    }
    .btn-upload{
      margin-bottom: 10px;
    }
  }
  .mask-upload{
    position: absolute;
    left: 0;
    top: 0;
    right:0;
    bottom:0;
    background: rgba($color: #000000, $alpha: 0);
    text-align: center;
    padding-top: 35px;
    padding-right:35px;
    width: 370px;
    .btn-cancel{
      position: absolute;
      right: 10px;
      top: 25px;
    }
  }
  .el-upload-list__item:hover {
    background-color: #F5F7FA;
    .option-box{
      display:block;
      color: $--color-primary;
      cursor: pointer;
  }
}
   .option-box{
     display: none;
    .option-icon{
      padding: 0 10px;
    }
  }
    .link-item{
      color: $--color-primary;
    }
/deep/.el-upload-list__item.is-success .el-upload-list__item-status-label {
    display: none;
}
/deep/.el-upload-list__item:hover .el-icon-close{
  display: none;
}
</style>
